#------------------------------------------------------------------------------ # This is a collection of procedures which help using the HttpRequestDll.dll. # While the same things could be achieved by a direct AdoScript "CALL", the # here provided procedures are supposed to make things simpler to use. # The provided procedures differ in three aspects: # * should Authentication be used? # * should the request body be base64 decoded before sending? # * should the response of a request be encoded in some way (e.g. because it # contains NUL bytes \0)? # # The procedures only work properly when the HttpRequestDll.dll is in the # right place (see global variable global_str_dll_httprequest). # # The DLL and the here provided procedures aren't too fancy, and try mostly to # remain as flexible as possible. As such there aren't different procedures for # the different HTTP methods and the procedures don't provide the luxury of # automatically processing "HTTP parameters" like other web-frameworks do ( a) # where the parameters are found varies from method to method and b) their # syntax depends on the used Content-Type). So parameters of a POST call have # to be put in manually as part of the body (e.g. in case of transmitting # 'application/x-www-form-urlencoded' content the body of a POST form call # is the parameters using a URL encoding). # However, there are now some functions to support encoding text using # URL encoding (used e.g. for 'application/x-www-form-urlencoded'). # # If you quickly want to jump through the different procedures available then # simply search for "PROCEDURE global". # # A small hint from the author: AdoScript maps are very similar to valid JSON. # An AdoScript map can be "transformed to a JSON string" using the STR function # and a string containing JSON can be "transformed to an AdoScript map" by # using AdoScripts EXECUTE command to set a variable, like: # SETL mymap:(eval(thejsonstring)) # or: # EXECUTE ("SETL mymap:(" + thejsonstring + ")") scope:same # As long as the keys are always of type string and the values are either # strings, numbers or other maps the concepts of AdoScript maps and JSON # overlap. # However, it is necessary to consider the differences between the two formats. # Besides ADOxx using ASCII/ANSI characters there are also other differences: # - AdoScript maps allow any data-type to be a key, while JSON requires keys to # be strings. # - AdoScript handles arrays using { and }, while JSON uses [ ]. Therefore # arrays between the two are not compatible. # - AdoScript doesn't know true, false and null. For boolean AdoScript uses # the numbers 0 and 1, but does not automatically transform true to 1 and # false to 0 (or vice versa). Instead, values that can't be handled become # of type "undefined" in AdoSCript. The typical null value can be compared to # AdoScript's "undefined" type, however the automatic transformation works # only in one direction: If the JSON contains null, it will be a value of # type "undefined" in the AdoScript map. # So, it is in many cases easy to send JSON requests by simply creating an # AdoScript map and transforming it to a string using STR. Using AdoScript maps # to process JSON responses can also be used in many cases. #------------------------------------------------------------------------------ # The global variable specifies the location of the DLL. # If it is a relative path, then the ADOxx installation folder is assumed. SETG global_str_dll_httprequest:("HttpRequestDll.dll") #------------------------------------------------------------------------------ # If the procedures provided here are to restrictive, then you can directly # CALL the required DLL. For details about the .DLL please see its Readme.txt, # which provides a description of the available functions and their parameters. # Example: IF (0) { # This sends an HTTP request to "http://localhost:8080/EchoService/e/", which # contains some request headers and a simple request body using the GET HTTP # method. The response is then shown in an EDITBOX and the response headers # are transformed and shown as an AdoScript map. # This map is used to represent the headers of the request SETL tempmap:({"Content-Type": "text/plain"}) # Perform the call actual call. CALL dll:"HttpRequestDll.dll" function:"long HRHttpCall(char* method, char* address, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:("GET") address:("http://localhost:8080/EchoService/e/") reqheaders:(STR tempmap) reqbody:("Somebody") result:respstat # Create a string that contains all of the response details and show it. SETL astext:(STR respstat + "\n\n" + respheaders + "\n\n" + respbody) CC "AdoScript" EDITBOX text:(astext) # Transform the response headers into a map and show that map. EXECUTE ("SETL tempmap:(" + respheaders + ")") scope:same CC "AdoScript" INFOBOX (type(tempmap) + "\n" + STR tempmap) # Using the provided procedures, the code would instead look like this: SETL tempmap:({"Content-Type": "text/plain"}) HTTP_SEND_REQUEST ("http://localhost:8080/EchoService/e/") str_method:("GET") map_reqheaders:(tempmap) str_reqbody:("Somebody") val_respcode:respstat map_respheaders:respheaders str_respbody:respbody SETL astext:(STR respstat + "\n\n" + STR respheaders + "\n\n" + respbody) CC "AdoScript" EDITBOX text:(astext) CC "AdoScript" INFOBOX (type(respheaders) + "\n" + STR respheaders) } #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_REQUEST string:str_url str_method:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference str_respbody:reference # Performs a normal HTTP request to the specified URL. The response is stored # in the corresponding parameters. # Important note: The call to the DLL assumes null-terminated C strings. As # such there can be problems when the response contains a NUL byte (\0) as part # of the content (e.g. like PNG images). If you anticipate this to be the case # please use one of the other procedures (HTTP_SEND_REQUEST_BASE or # HTTP_SEND_REQUEST_BYTES). # str_url - The main parameter should specify the URL where the request should # be sent. In case of GET requests the "HTTP parameters" should be part of # the URL query. # str_method - Which HTTP method should be used. Common are GET, PUT, POST, # DELETE, but also HEAD, OPTIONS, TRACE and others are possible. Just # remember that the standardized HTTP methods should use upper case. # map_reqheaders - A map containing the headers to be sent with this request. # "Host" and "Content-Length" seem to always be present automatically, but # others like "Accept", "Content-Type" or "Authorization" have to be # specified through this map. In any case both the keys and the values of # the map should be strings, or if you don't want to specify any additional # headers just use (map()) for this parameter. # str_reqbody - The body that should be sent with the request. In case of "PUT" # and "POST" requests it should contain the desired parameters, which can # be simple in some cases (e.g. a string containing valid JSON code), but # more complicated in others (e.g. an application/x-www-form-urlencoded # request has to URL-encode the parameters). It is up to the procedure # caller to produce the proper body content. # val_respcode - a reference that will contain the HTTP status code answered # by the server or possibly 0 if something went wrong before the request # could be sent. # map_respheaders - a reference that will contain an AdoScript map with the # response headers. Both the keys and the values will be of type string. # str_respbody - a reference that will contain the response of the server as # a string or more details about an error if something has gone wrong. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRHttpCall(char* method, char* address, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } SETL str_respbody:(respbody) } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_AUTH_REQUEST string:str_url str_method:string str_username:string str_password:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference str_respbody:reference # Performs an HTTP request with basic authentication to the specified URL. The # response is stored in the corresponding parameters. # Important note: The call to the DLL assumes null-terminated C strings. As # such there can be problems when the response contains a NUL byte (\0) as part # of the content (e.g. like PNG images). If you anticipate this to be the case # please use one of the other procedures (HTTP_SEND_AUTH_REQUEST_BASE or # HTTP_SEND_AUTH_REQUEST_BYTES). # str_url - The main parameter should specify the URL where the request should # be sent. In case of GET requests the "HTTP parameters" should be part of # the URL query. # str_method - Which HTTP method should be used. Common are GET, PUT, POST, # DELETE, but also HEAD, OPTIONS, TRACE and others are possible. Just # remember that the standardized HTTP methods should use upper case. # str_username - The user name to use with basic authentication. # str_password - The password to use with basic authentication. # map_reqheaders - A map containing the headers to be sent with this request. # "Host" and "Content-Length" seem to always be present automatically, but # others like "Accept", "Content-Type" or "Authorization" have to be # specified through this map. In any case both the keys and the values of # the map should be strings, or if you don't want to specify any additional # headers just use (map()) for this parameter. # str_reqbody - The body that should be sent with the request. In case of "PUT" # and "POST" requests it should contain the desired parameters, which can # be simple in some cases (e.g. a string containing valid JSON code), but # more complicated in others (e.g. a application/x-www-form-urlencoded # request has to url-encode the parameters). It is up to the procedure # caller to produce the proper body content. # val_respcode - a reference that will contain the HTTP status code answered # by the server or possibly 0 if something went wrong before the request # could be sent. # map_respheaders - a reference that will contain an AdoScript map with the # response headers. Both the keys and the values will be of type string. # str_respbody - a reference that will contain the response of the server as # a string or more details about an error if something has gone wrong. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRAuthHttpCall(char* method, char* address, char* uname, char* upw, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) uname:(str_username) upw:(str_password) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } SETL str_respbody:(respbody) } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_REQUEST_BASE string:str_url str_method:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference str_respbody:reference # Performs a normal HTTP request to the specified URL. The response is stored # in the corresponding parameters. Unlike HTTP_SEND_REQUEST a successful # response will be encoded as base64. This can be important when the content of # the response can contain NUL bytes (\0). # str_url - The main parameter should specify the URL where the request should # be sent. In case of GET requests the "HTTP parameters" should be part of # the URL query. # str_method - Which HTTP method should be used. Common are GET, PUT, POST, # DELETE, but also HEAD, OPTIONS, TRACE and others are possible. Just # remember that the standardized HTTP methods should use upper case. # map_reqheaders - A map containing the headers to be sent with this request. # "Host" and "Content-Length" seem to always be present automatically, but # others like "Accept", "Content-Type" or "Authorization" have to be # specified through this map. In any case both the keys and the values of # the map should be strings, or if you don't want to specify any additional # headers just use (map()) for this parameter. # str_reqbody - The body that should be sent with the request. In case of "PUT" # and "POST" requests it should contain the desired parameters, which can # be simple in some cases (e.g. a string containing valid JSON code), but # more complicated in others (e.g. a application/x-www-form-urlencoded # request has to url-encode the parameters). It is up to the procedure # caller to produce the proper body content. # val_respcode - a reference that will contain the HTTP status code answered # by the server or possibly 0 if something went wrong before the request # could be sent. # map_respheaders - a reference that will contain an AdoScript map with the # response headers. Both the keys and the values will be of type string. # str_respbody - a reference that will contain the response of the server or # the error message as a base64 encoded string. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRHttpCallBase64(char* method, char* address, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } SETL str_respbody:(respbody) } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_AUTH_REQUEST_BASE string:str_url str_method:string str_username:string str_password:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference str_respbody:reference # Performs an HTTP request with basic authentication to the specified URL. The # response is stored in the corresponding parameters. Unlike # HTTP_SEND_AUTH_REQUEST a successful response will be encoded as base64. This # can be important when the content of the response can contain NUL bytes (\0). # str_url - The main parameter should specify the URL where the request should # be sent. In case of GET requests the "HTTP parameters" should be part of # the URL query. # str_method - Which HTTP method should be used. Common are GET, PUT, POST, # DELETE, but also HEAD, OPTIONS, TRACE and others are possible. Just # remember that the standardized HTTP methods should use upper case. # str_username - The user name to use with basic authentication. # str_password - The password to use with basic authentication. # map_reqheaders - A map containing the headers to be sent with this request. # "Host" and "Content-Length" seem to always be present automatically, but # others like "Accept", "Content-Type" or "Authorization" have to be # specified through this map. In any case both the keys and the values of # the map should be strings, or if you don't want to specify any additional # headers just use (map()) for this parameter. # str_reqbody - The body that should be sent with the request. In case of "PUT" # and "POST" requests it should contain the desired parameters, which can # be simple in some cases (e.g. a string containing valid JSON code), but # more complicated in others (e.g. a application/x-www-form-urlencoded # request has to url-encode the parameters). It is up to the procedure # caller to produce the proper body content. # val_respcode - a reference that will contain the HTTP status code answered # by the server or possibly 0 if something went wrong before the request # could be sent. # map_respheaders - a reference that will contain an AdoScript map with the # response headers. Both the keys and the values will be of type string. # str_respbody - a reference that will contain the response of the server or # the error message as a base64 encoded string. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRAuthHttpCallBase64(char* method, char* address, char* uname, char* upw, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) uname:(str_username) upw:(str_password) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } SETL str_respbody:(respbody) } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_REQUEST_BYTES string:str_url str_method:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference arr_respbody:reference # Performs a normal HTTP request to the specified URL. The response is stored # in the corresponding parameters. Unlike HTTP_SEND_REQUEST a successful # response will be an array of bytes. The bytes are in the decimal number # system. This can be important when the content of the response can contain # NUL bytes (\0). # str_url - The main parameter should specify the URL where the request should # be sent. In case of GET requests the "HTTP parameters" should be part of # the URL query. # str_method - Which HTTP method should be used. Common are GET, PUT, POST, # DELETE, but also HEAD, OPTIONS, TRACE and others are possible. Just # remember that the standardized HTTP methods should use upper case. # map_reqheaders - A map containing the headers to be sent with this request. # "Host" and "Content-Length" seem to always be present automatically, but # others like "Accept", "Content-Type" or "Authorization" have to be # specified through this map. In any case both the keys and the values of # the map should be strings, or if you don't want to specify any additional # headers just use (map()) for this parameter. # str_reqbody - The body that should be sent with the request. In case of "PUT" # and "POST" requests it should contain the desired parameters, which can # be simple in some cases (e.g. a string containing valid JSON code), but # more complicated in others (e.g. a application/x-www-form-urlencoded # request has to url-encode the parameters). It is up to the procedure # caller to produce the proper body content. # val_respcode - a reference that will contain the HTTP status code answered # by the server or possibly 0 if something went wrong before the request # could be sent. # map_respheaders - a reference that will contain an AdoScript map with the # response headers. Both the keys and the values will be of type string. # arr_respbody - a reference that will contain the response of the server or # the error message as an array of bytes in the decimal number system. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRHttpCallBytes(char* method, char* address, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } EXECUTE ("SETL arr_respbody:({" + respbody + "})") scope:same } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_AUTH_REQUEST_BYTES string:str_url str_method:string str_username:string str_password:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference arr_respbody:reference # Performs an HTTP request with basic authentication to the specified URL. The # response is stored in the corresponding parameters. Unlike # HTTP_SEND_AUTH_REQUEST a successful response will be an array of bytes. The # bytes are in the decimal number system. This can be important when the # content of the response can contain NUL bytes (\0). # str_url - The main parameter should specify the URL where the request should # be sent. In case of GET requests the "HTTP parameters" should be part of # the URL query. # str_method - Which HTTP method should be used. Common are GET, PUT, POST, # DELETE, but also HEAD, OPTIONS, TRACE and others are possible. Just # remember that the standardized HTTP methods should use upper case. # str_username - The user name to use with basic authentication. # str_password - The password to use with basic authentication. # map_reqheaders - A map containing the headers to be sent with this request. # "Host" and "Content-Length" seem to always be present automatically, but # others like "Accept", "Content-Type" or "Authorization" have to be # specified through this map. In any case both the keys and the values of # the map should be strings, or if you don't want to specify any additional # headers just use (map()) for this parameter. # str_reqbody - The body that should be sent with the request. In case of "PUT" # and "POST" requests it should contain the desired parameters, which can # be simple in some cases (e.g. a string containing valid JSON code), but # more complicated in others (e.g. a application/x-www-form-urlencoded # request has to url-encode the parameters). It is up to the procedure # caller to produce the proper body content. # val_respcode - a reference that will contain the HTTP status code answered # by the server or possibly 0 if something went wrong before the request # could be sent. # map_respheaders - a reference that will contain an AdoScript map with the # response headers. Both the keys and the values will be of type string. # arr_respbody - a reference that will contain the response of the server or # the error message as an array of bytes in the decimal number system. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRAuthHttpCallBytes(char* method, char* address, char* uname, char* upw, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) uname:(str_username) upw:(str_password) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } EXECUTE ("SETL arr_respbody:({" + respbody + "})") scope:same } ############################################################################### # The detailed documentation has been mostly skipped for some of the following # procedures, since they are mostly the same. # They are a special version of the previous procedures which will decode the # str_reqbody using base64 before sending it to the specified URL. If you want # to send the data still base64 encoded then use the previous procedures. # Otherwise they behave the same. ############################################################################### #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_REQUEST_INBASE string:str_url str_method:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference str_respbody:reference # Same as previous procedure HTTP_SEND_REQUEST, only that it expects the # request body (str_reqbody) to be base64 encoded and decodes it to a plain # string before sending it to the server. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRHttpCallIn64(char* method, char* address, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } SETL str_respbody:(respbody) } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_AUTH_REQUEST_INBASE string:str_url str_method:string str_username:string str_password:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference str_respbody:reference # Same as previous procedure HTTP_SEND_AUTH_REQUEST, only that it expects the # request body (str_reqbody) to be base64 encoded and decodes it to a plain # string before sending it to the server. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRAuthHttpCallIn64(char* method, char* address, char* uname, char* upw, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) uname:(str_username) upw:(str_password) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } SETL str_respbody:(respbody) } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_REQUEST_BASE_INBASE string:str_url str_method:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference str_respbody:reference # Same as previous procedure HTTP_SEND_REQUEST_BASE, only that it expects the # request body (str_reqbody) to be base64 encoded and decodes it to a plain # string before sending it to the server. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRHttpCallBase64In64(char* method, char* address, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } SETL str_respbody:(respbody) } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_AUTH_REQUEST_BASE_INBASE string:str_url str_method:string str_username:string str_password:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference str_respbody:reference # Same as previous procedure HTTP_AUTH_SEND_REQUEST_BASE, only that it expects # the request body (str_reqbody) to be base64 encoded and decodes it to a plain # string before sending it to the server. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRAuthHttpCallBase64In64(char* method, char* address, char* uname, char* upw, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) uname:(str_username) upw:(str_password) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } SETL str_respbody:(respbody) } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_REQUEST_BYTES_INBASE string:str_url str_method:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference arr_respbody:reference # Same as previous procedure HTTP_SEND_REQUEST_BYTES, only that it expects the # request body (str_reqbody) to be base64 encoded and decodes it to a plain # string before sending it to the server. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRHttpCallBytesIn64(char* method, char* address, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } EXECUTE ("SETL arr_respbody:({" + respbody + "})") scope:same } #------------------------------------------------------------------------------ PROCEDURE global HTTP_SEND_AUTH_REQUEST_BYTES_INBASE string:str_url str_method:string str_username:string str_password:string map_reqheaders:map str_reqbody:string val_respcode:reference map_respheaders:reference arr_respbody:reference # Same as previous procedure HTTP_SEND_AUTH_REQUEST_BYTES, only that it expects # the request body (str_reqbody) to be base64 encoded and decodes it to a plain # string before sending it to the server. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } CALL dll:(global_str_dll_httprequest) function:"long HRAuthHttpCallBytesIn64(char* method, char* address, char* uname, char* upw, char* reqheaders, char* reqbody, char** respheaders, char** respbody)" method:(str_method) address:(str_url) uname:(str_username) upw:(str_password) reqheaders:(STR map_reqheaders) reqbody:(str_reqbody) result:val_respcode EXECUTE ("SETL map_respheaders:(" + respheaders + ")") scope:same IF (type(map_respheaders) = "array") { SETL map_respheaders:(map()) } EXECUTE ("SETL arr_respbody:({" + respbody + "})") scope:same } ############################################################################### # The following procedures are to help with some of the tasks facing when # calling a service via HTTP. ############################################################################### #------------------------------------------------------------------------------ PROCEDURE global HTTP_URL_ENCODE string:str_content str_allowedset:string str_encoded:reference # Takes a text and uses URL encoding to escape any unsafe/not-allowed # characters. Characters which are not allowed are replaced with one or more # %xx where xx is an 8-bit hexadecimal number. Useful for sending POST requests # with content-type 'application/x-www-form-urlencoded'. # str_content - The content that should be encoded using URL encoding style. # Consider providing the main parameter with the toutf8(...) function of # ADOxx, since most web things work with UTF-8 while ADOxx seems to use # Windows-1252. Using toutf8(...) on the main parameter will for example # encode the small a-umlaut as %C3%A4 (as should be for UTF-8) instead of # just %E4. If you're only using the ASCII characters then toutf8(...) # shouldn't be necessary. # str_allowedset - Should be "JS", "Inter", "Lax" or "VeryLax". If an unknown # value is specified then "JS" will be used by default. This parameter # specifies which of the four available sets containing the "allowed # characters" to use. Anything that isn't an allowed character will be # encoded. # "JS" allows the same characters as the on the Java Script # encodeURIComponent() function (from Firefox / Chrome). Probably the # safest bet in most cases. # "Inter" is a list of characters based from several sources, including the # URI specification. # "Lax" allows everything except non-ASCII characters, ASCII control # characters (0x00 to 0x20 and 0x7F), # (0x23), % (0x25), & (0x26), # + (0x2B), = (0x3D) and ? (0x3F) # "VeryLax" allows everything except non-ASCII characters, ASCII control # characters (0x00 to 0x20 and 0x7F), % (0x25), & (0x26) and = (0x3D) # str_encoded - a reference that will contain the encoded content. Will only # consist of the characters from the allowed set and % used to encode other # characters. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } IF (str_allowedset = "Inter") { CALL dll:(global_str_dll_httprequest) function:"char* HRUrlEncodeInter(char* text)" text:(str_content) result:str_encoded } ELSIF (str_allowedset = "Lax") { CALL dll:(global_str_dll_httprequest) function:"char* HRUrlEncodeLax(char* text)" text:(str_content) result:str_encoded } ELSIF (str_allowedset = "VeryLax") { CALL dll:(global_str_dll_httprequest) function:"char* HRUrlEncodeVeryLax(char* text)" text:(str_content) result:str_encoded } ELSE { CALL dll:(global_str_dll_httprequest) function:"char* HRUrlEncodeJS(char* text)" text:(str_content) result:str_encoded } } #------------------------------------------------------------------------------ PROCEDURE global HTTP_URL_ENCODE_QUERY map:map_content str_allowedset:string str_encoded:reference # Takes a map containing key-value pairs and uses URL encoding to escape any # unsafe/not-allowed characters and builds a string which follows the structure # of the query-portion of a URL. This is used for example by data which is sent # as 'application/x-www-form-urlencoded' Characters which are not allowed are # replaced with one or more %xx where xx is an 8-bit hexadecimal number. # map_content - a map containing keys and their values which should be # transformed into the structure of the URL-query-portion. When creating # the map consider using the toutf8(...) function of ADOxx for the keys # and values (especially the values), since most web things work with # UTF-8 while ADOxx seems to use Windows-1252. Using toutf8(...) on the # main parameter will for example encode the small a-umlaut as %C3%A4 (as # should be for UTF-8) instead of just %E4. If you're only using the ASCII # characters then toutf8(...) shouldn't be necessary. # Both the keys and the values of the map have to be of type string. # str_allowedset - Should be "JS", "Inter", "Lax" or "VeryLax". If an unknown # value is specified then "JS" will be used by default. This parameter # specifies which of the four available sets containing the "allowed # characters" to use. Anything that isn't an allowed character will be # encoded. # "JS" allows the same characters as the on the Java Script # encodeURIComponent() function (from Firefox / Chrome). Probably the # safest bet in most cases. # "Inter" is a list of characters based from several sources, including the # URI specification. # "Lax" allows everything except non-ASCII characters, ASCII control # characters (0x00 to 0x20 and 0x7F), # (0x23), % (0x25), & (0x26), # + (0x2B), = (0x3D) and ? (0x3F) # "VeryLax" allows everything except non-ASCII characters, ASCII control # characters (0x00 to 0x20 and 0x7F), % (0x25), & (0x26) and = (0x3D) # str_encoded - a reference that will contain the encoded content. Will only # consist of the characters from the allowed set, % used to encode other # characters and & and = which are used by # 'application/x-www-form-urlencoded'. #------------------------------------------------------------------------------ { CC "AdoScript" FILE_EXISTS file:(global_str_dll_httprequest) IF (NOT exists) { CC "AdoScript" ERRORBOX ("The necessary DLL could not be found at\n" + global_str_dll_httprequest) title:("File not found") EXIT } IF (str_allowedset = "Inter") { CALL dll:(global_str_dll_httprequest) function:"char* HRUrlEncodeQueryInter(char* paramsjson)" paramsjson:(STR map_content) result:str_encoded } ELSIF (str_allowedset = "Lax") { CALL dll:(global_str_dll_httprequest) function:"char* HRUrlEncodeQueryLax(char* paramsjson)" paramsjson:(STR map_content) result:str_encoded } ELSIF (str_allowedset = "VeryLax") { CALL dll:(global_str_dll_httprequest) function:"char* HRUrlEncodeQueryVeryLax(char* paramsjson)" paramsjson:(STR map_content) result:str_encoded } ELSE { CALL dll:(global_str_dll_httprequest) function:"char* HRUrlEncodeQueryJS(char* paramsjson)" paramsjson:(STR map_content) result:str_encoded } }